package com.imflea.zero.service.cms.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.imflea.zero.util.base.CommonUtils;
import com.imflea.zero.constant.MallContant;
import com.imflea.zero.constant.MallPromptContant;
import com.imflea.zero.dto.PageDto;
import com.imflea.zero.exception.BizException;
import com.imflea.zero.model.dao.cms.CmsEnterpriseNewsMapper;
import com.imflea.zero.model.entity.cms.CmsEnterpriseNews;
import com.imflea.zero.model.entity.cms.dto.CmsEnterpriseNewsDto;
import com.imflea.zero.model.entity.cms.vo.EnterpriseNewsVo;
import com.imflea.zero.service.cms.ICmsEnterpriseNewsService;
import com.imflea.zero.utils.AssertUtil;
import com.imflea.zero.utils.HighLevelClientUtils;
import com.imflea.zero.utils.RestUtil;
import com.imflea.zero.utils.SessionUtils;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;

/**
 * <p>
 * 企业资讯 服务实现类
 * </p>
 *
 * @author zhaoyang
 * @since 2021-09-24
 */
@Service
public class CmsEnterpriseNewsServiceImpl extends ServiceImpl<CmsEnterpriseNewsMapper, CmsEnterpriseNews> implements ICmsEnterpriseNewsService {

    @Autowired
    private RestHighLevelClient restHighLevelClient;

    private static final String ES_DOC_ENTERPRISE_NEWS = "enterprise_news";

    @Override
    public CmsEnterpriseNews saveOrUpdateCmsEnterpriseNews(CmsEnterpriseNews entity) {

        if (CommonUtils.isNull(entity.getId())) {
            entity.setId(CommonUtils.generateRandomString());
            entity.setTenantId(SessionUtils.getTenantId());
            entity.setPublishStatus(MallContant.ZERO);
        }
        boolean success = this.saveOrUpdate(entity);
        return RestUtil.orElseThrow(success, entity, "保存(更新)操作失败");
    }

    @Override
    public PageInfo<CmsEnterpriseNews> queryPage(CmsEnterpriseNewsDto dto) {

        QueryWrapper<CmsEnterpriseNews> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("TENANT_ID", SessionUtils.getTenantId());

        Date publishDate = dto.getPublishDate();
        if (!CommonUtils.isNull(publishDate)) {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            queryWrapper.eq("DATE_FORMAT(PUBLISH_DATE, '%Y-%m-%d')", sdf.format(publishDate));
        }

        String title = dto.getTitle();
        queryWrapper.like(!CommonUtils.isNull(title), "TITLE", title);

        String label = dto.getLabel();
        queryWrapper.like(!CommonUtils.isNull(label), "LABEL", label);

        String author = dto.getAuthor();
        queryWrapper.like(!CommonUtils.isNull(author), "AUTHOR", author);

        queryWrapper.orderByAsc("PUBLISH_STATUS");
        queryWrapper.orderByDesc("PUBLISH_DATE", "CREATE_TIME");

        Integer pageIndex = dto.getPageNum();
        Integer pageSize = dto.getPageSize();
        PageHelper.startPage(pageIndex, pageSize);
        List<CmsEnterpriseNews> adoptInfos = this.list(queryWrapper);
        PageInfo<CmsEnterpriseNews> pageResult = new PageInfo<>(adoptInfos);
        return pageResult;
    }

    @Override
    public Boolean updatePublishStatus(CmsEnterpriseNewsDto dto) {

        String id = dto.getId();
        AssertUtil.mustNotEmpty(id, MallPromptContant.ID_NOT_EMPTY);

        Integer publishStatus = dto.getPublishStatus();
        AssertUtil.mustNotEmpty(publishStatus, "发布状态为空");

        CmsEnterpriseNews esNews = this.getById(id);
        // 已经发布的新闻无需重复发布
        if (publishStatus.equals(esNews.getPublishStatus())) {
            return true;
        }

        push2ES(publishStatus, esNews);

        CmsEnterpriseNews news = buildPublishNews(id, publishStatus);

        return this.updateById(news);
    }


    @Override
    public EnterpriseNewsVo queryPageFormEs(PageDto pageDto) {

        Integer from = pageDto.getPageNum();
        Integer size = pageDto.getPageSize();

        if (CommonUtils.isNull(from) || from <= MallContant.ZERO) {
            from = 0;
        } else {
            from = (from - 1) * size;
        }
        if (CommonUtils.isNull(size)) {
            size = 10;
        }

        BoolQueryBuilder query = QueryBuilders.boolQuery()
                .must(QueryBuilders.termQuery("tenantId", SessionUtils.getTenantId()));
        SearchSourceBuilder searchBuilder = new SearchSourceBuilder();
        searchBuilder.query(query);
        searchBuilder.from(from).size(size);
        searchBuilder.sort("publishDate", SortOrder.DESC);

        SearchResponse response = HighLevelClientUtils.search(restHighLevelClient, ES_DOC_ENTERPRISE_NEWS, searchBuilder);

        EnterpriseNewsVo newsVo = new EnterpriseNewsVo();

        if (RestStatus.OK.equals(response.status())) {
            List<Map<String, Object>> result = new ArrayList<>();
            SearchHits hits = response.getHits();
            newsVo.setTotal(hits.getTotalHits().value);
            SearchHit[] searchHits = hits.getHits();
            for (SearchHit searchHit : searchHits) {
                Map<String, Object> source = searchHit.getSourceAsMap();
                result.add(source);
            }
            newsVo.setList(result);
        }
        return newsVo;
    }

    @Override
    public Map<String, Object> queryNewsFromEs(String newsId) {

        SearchSourceBuilder searchBuilder = new SearchSourceBuilder();
        searchBuilder.query(QueryBuilders.termQuery("id", newsId));

        SearchResponse response = HighLevelClientUtils.search(restHighLevelClient, ES_DOC_ENTERPRISE_NEWS, searchBuilder);

        if (response != null && RestStatus.OK.equals(response.status()) && response.getHits().getTotalHits().value > MallContant.ZERO) {
            return response.getHits()
                    .getAt(MallContant.ZERO)
                    .getSourceAsMap();
        }
        return Collections.emptyMap();
    }

    @Override
    public boolean removeEntity(List<String> ids) {

        AssertUtil.mustNotEmpty(ids, MallPromptContant.ID_NOT_EMPTY);

        List<CmsEnterpriseNews> news = this.listByIds(ids);
        if (CommonUtils.isNull(news)) {
            return true;
        }

        for (CmsEnterpriseNews cmsEnterpriseNews : news) {
            if (cmsEnterpriseNews.getPublishStatus() == MallContant.ONE) {
                throw new BizException("[" + cmsEnterpriseNews.getTitle() + "],已发布,不能直接删除");
            }
        }
        boolean success = this.removeByIds(ids);
        return RestUtil.orElseThrow(success, "新闻删除失败");
    }

    private CmsEnterpriseNews buildPublishNews(String id, Integer publishStatus) {
        CmsEnterpriseNews news = new CmsEnterpriseNews();
        news.setId(id);
        news.setPublishStatus(publishStatus);
        if (CommonUtils.isNull(news.getPublishDate())) {
            news.setPublishDate(LocalDateTime.now());
        }
        return news;
    }

    /**
     * 根据发布状态将新闻信息推送到ES中
     */
    private void push2ES(Integer publishStatus, CmsEnterpriseNews esNews) {
        if (MallContant.ZERO == publishStatus) {
            HighLevelClientUtils.deleteDoc(restHighLevelClient, ES_DOC_ENTERPRISE_NEWS, esNews.getId());
        } else if (MallContant.ONE == publishStatus) {
            LocalDateTime publishDate = esNews.getPublishDate();
            if (CommonUtils.isNull(publishDate)) {
                esNews.setPublishDate(LocalDateTime.now());
            }
            HighLevelClientUtils.updateDoc(restHighLevelClient, ES_DOC_ENTERPRISE_NEWS, esNews, esNews.getId());
        }
    }

}
